package com.baofu.paycore.biz.engine.executor.impl;

import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.google.common.collect.Maps;
import com.baofu.paycore.biz.engine.command.Command;
import com.baofu.paycore.biz.engine.executor.CommandExecutor;
import com.baofu.paycore.biz.engine.processor.BaseProcessor;
import com.baofu.paycore.biz.engine.processor.ProcessorContainer;
import com.baofu.paycore.biz.engine.result.CommandResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 命令执行器
 *
 * <p/>
 *      1、执行命令
 * </p>
 * User: LZQ Date: 2016/04/22  Version: 1.0
 */
@Slf4j
@Service
public class CommandExecutorImpl implements CommandExecutor {

    /** 处理器容器  */
    @Autowired
    private ProcessorContainer processorContainer;

    /**
     * 指令执行
     * @param commands 命令
     * @return         执行结果
     */
    @Override
    public Map<String, CommandResult> executeCommand(List<Command> commands) {

        Map<String, CommandResult> results = Maps.newHashMap();
        for (Command command : commands) {

            BaseProcessor<Command> processor = processorContainer.getProcessor(command.getProcessorType());

            log.debug("处理器:{} 命令类型 {}",processor,command.getCommandType());
            Map<String, CommandResult> eachResult = processor.doProcess(command);
            results.putAll(eachResult);
            if (haveFailResult(eachResult)) {
                // // TODO: 16/7/6 do cancel
                break;
            }
        }
        return results;
    }

    /**
     * 检查是否有失败的结果
     * 
     * @param checkResult 命令执行结果集
     * @return            结果集包含失败
     */
    private boolean haveFailResult(Map<String, CommandResult> checkResult) {
        Collection<CommandResult> values = checkResult.values();
        for (CommandResult result : values) {
            if (!result.isRealRtnFlag() || ! Objects.equals(PayStatusEnums.SUCCESS.getCode(),result.getStatus())) {
                return true;
            }
        }
        return false;
    }

}
